/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "Log.h"
#include "File.h"
#include <Gluck.h>
#include <filesystem/String.hpp>

#include <log4cplus/logger.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/configurator.h>

#if defined (WIN32)
#ifdef _DEBUG
#pragma comment(lib, "log4cplusD.lib")
#else
#pragma comment(lib, "log4cplus.lib")
#endif
#endif

#include <system/StringFunctions.h>
#include <boost/scoped_array.hpp>

namespace liba
{
namespace logs
{

static Log<char> * static_log = 0;
static Log<wchar_t> * static_wlog = 0;

Creator::Creator(const std::string & app_name)
{
	if( static_log )
		THROW(Gluck(__FUNCTION__, "Log char already exists"));

#ifdef ANDROID_NDK

    __android_log_print(ANDROID_LOG_INFO, "APK", "creating console log...");
	static_log = new Dummy<char>();
#else
	#if defined(IPHONE_VERSION) || defined(SAMSUNG_VERSION)
	//	static_log = new File<char>( filesystem::String("%local_appdata%/") + "/"  + "%app_name%.log");
		static_log = new Dummy<char>();
	#else
		static_log = new File<char>( filesystem::String("%local_appdata%/") + app_name.c_str() + "/"  + "%app_name%.log");
	#endif
#endif

#ifdef WIN32
	log4cplus::PropertyConfigurator::doConfigure((app_name + ".log4cplus").c_str());
#else
	log4cplus::BasicConfigurator::doConfigure();
#endif

//	static_wlog = 0; // TODO: create redirector to static_log with conversion
}

Creator::Creator(Log<char> * l)
{
	if( static_log )
		THROW(Gluck(__FUNCTION__, "Log char already exists"));
	static_log = l;
//	static_wlog = 0; // TODO: create redirector to static_log with conversion
}

Creator::Creator(Log<wchar_t> * wl)
{
	if( static_wlog )
		THROW(Gluck(__FUNCTION__, "Log wchar_t already exists"));
//	static_log = 0; // TODO: create redirector to static_wlog with conversion
	static_wlog = wl;
}

Creator::~Creator()
{
	delete static_log; static_log = 0;
	delete static_wlog; static_wlog = 0;
}

Log<char> & log()
{
	return *static_log;
}

Log<wchar_t> & wlog()
{
	return *static_wlog;
}

bool IsLogLevelEnabled(const char* loggerName, LogLevel level)
{
	log4cplus::Logger l = log4cplus::Logger::getInstance(loggerName);
	return l.isEnabledFor((log4cplus::LogLevel)level);
}

void DoLog(const char* loggerName, LogLevel level, const char* file, int line, const char* format, ...)
{
	log4cplus::Logger l = log4cplus::Logger::getInstance(loggerName);

	static size_t bufferSize = 256;
	static boost::scoped_array<char> buffer(new char[bufferSize]);

	va_list args;
	va_start(args, format);
	while (system::_vsnprintf_s(buffer.get(), bufferSize, bufferSize - 1, format, args) < 0)
	{
		bufferSize *= 2;
		buffer.reset(new char[bufferSize]);
	}

	va_end(args);

	l.forcedLog((log4cplus::LogLevel)level, buffer.get(), file, line);
}

} // namespace logs
} // namespace liba
